#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include "uart.h"

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>

volatile char msg_rx[SERIAL_BUF_SIZE];
volatile char msg_tx[SERIAL_BUF_SIZE];
volatile uint8_t rx_buf_pos;
volatile uint8_t tx_buf_pos;
volatile uint8_t serial_rx;

ISR(USART_RX_vect) {

  /* Gets byte from register */
  char rx_char = UDR0;

  /* Check if it's end of msg (/n) */
  /* or just the middle. */
  if (rx_char=='\n') {
    msg_rx[rx_buf_pos++] = rx_char;
    msg_rx[rx_buf_pos++] = '\0';
    if (serial_rx==0) serial_rx = 1;
  } 
  else {
    msg_rx[rx_buf_pos++] = rx_char;
  }
  
  /* Ooops, msg is too big. Let's loop */
  if (rx_buf_pos==SERIAL_BUF_SIZE-1) rx_buf_pos=0;
}

ISR(USART_UDRE_vect) {
  
  /* See if it isn't the end yet */
  /* If it it is, disable the interrupt */
  /* and reset transmission buffer */
  if (msg_tx[tx_buf_pos] != '\0') {
    UDR0 = msg_tx[tx_buf_pos++];
  }
  else {
    UCSR0B &= ~(1 << UDRIE0);
    tx_buf_pos = 0;
  }
}

void uart_init(unsigned int bittimer)
{
  /* Set the baud rate */
  UBRR0H = (unsigned char) (bittimer >> 8);
  UBRR0L = (unsigned char) bittimer;
  /* Set the framing to 8N1 */
  UCSR0C = (3 << UCSZ00);
  /* Enable RX Interrupt and Engage!*/
  UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
  /* Initialize USART Variables */
  serial_rx = 0;
  tx_buf_pos = 0;
  rx_buf_pos = 0;
}

void uart_transmit(char* msg)
{
  
  /* Copy msg to buffer msg_tx, reset buffer */
  /* (just for precaution) and enable interrupt */
  /* for transmission. ISR will flush msg_tx */
  strcpy((char*) msg_tx,msg);
  tx_buf_pos = 0;
  UCSR0B |= (1 << UDRIE0);
}

void uart_read_buffer(char *msg_var)
{

  /* Reset receiver buffer and receiver flag */
  /* Copy msg from buffer to given string adress */
  serial_rx = 0;
  rx_buf_pos = 0;
  strcpy(msg_var,(char*) msg_rx);

}
